package datasource.social;

import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
import java.util.StringTokenizer;

import javax.imageio.ImageIO;

import summarizer.PinakiSummarizer;
import summarizer.newversion.ClusterSummarizer;
import summarizer.newversion.GreedySummarizerItOptNewFilter;
import summarizer.newversion.RandomSummarizer;
import summarizer.newversion.Summarizer;
import thesis.DataObject;
import thesis.InfoUnit;
import thesis.Summary;

import com.aliasi.util.Pair;

import datasource.image.ImageObj;
import datasource.image.ImageUtil;
import datasource.image.TimeClustering;
import experiment.Dimension;
import experiment.MainExp;
import experiment.Preprocess;

public class SocialPhoto {
	private static String root = "C:\\home\\work\\tweet_project\\datasets\\pictures from FB";

	public static ArrayList<ImageObj> readData(String root) {
		File rootDir = new File(root);
		int count = 0;
		ArrayList<ImageObj> imgs = new ArrayList<ImageObj>();
		for (File user : rootDir.listFiles()) {
			for (File event : user.listFiles()) {
				for (File img : event.listFiles()) {
					String imgName = img.getAbsolutePath();
					if (imgName.endsWith(".jpg")) {
						count++;
						String metaName = imgName.substring(0,
								imgName.lastIndexOf("."))
								+ ".txt";
						ImageObj obj = new ImageObj(count);
						obj.addEventTag(event.getName().toLowerCase(), 1.0);
						obj.userId = user.getName().toLowerCase();
						obj.time = ImageUtil.stringDate2Long(img.getName()
								.substring(0, img.getName().lastIndexOf('.')));
						try {
							File metaFile = new File(metaName);
							if (metaFile.exists()) {
								imgs.add(obj);
								obj.path = img.getAbsolutePath();
								BufferedReader br = new BufferedReader(
										new FileReader(metaFile));
								// parse people names
								String peopleLine = br.readLine();
								StringTokenizer st = new StringTokenizer(
										peopleLine, ":");
								st.nextToken();
								if (st.hasMoreTokens()) {
									StringTokenizer peopleNames = new StringTokenizer(
											st.nextToken(), ",");
									while (peopleNames.hasMoreTokens()) {
										String tmp = peopleNames.nextToken()
												.toLowerCase().trim();
										if (!tmp.isEmpty()) {
											obj.addPeople(tmp, 1.0);
										}
									}
								}
								// parse concepts
								String concepts = br.readLine();
								st = new StringTokenizer(concepts, ":");
								st.nextToken();
								if (st.hasMoreTokens()) {
									StringTokenizer conceptNames = new StringTokenizer(
											st.nextToken(), ",");
									while (conceptNames.hasMoreTokens()) {
										String tmp = conceptNames.nextToken()
												.toLowerCase().trim();
										if (!tmp.isEmpty()) {
											obj.addConcept(tmp, 1.0);
										}
									}
								}
								br.close();
							}
						} catch (IOException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}

					}
				}
			}
		}
		System.out.println("Total number of images: " + count);
		return imgs;
	}

	private static List<Dimension> generateDim(ArrayList<ImageObj> objs) {
		Dimension timeDim = new Dimension();
		Dimension eventDim = new Dimension();
		Dimension idDim = new Dimension();
		Dimension visualDim = new Dimension();
		Dimension peopleDim = new Dimension();
		for (ImageObj obj : objs) {
			// time ------------
			if (obj.time != null) {
				HashMap<Long, Double> timeValue = timeDim.value2obj.get(""
						+ obj.timeClusterID);
				if (timeValue == null) {
					timeValue = new HashMap<Long, Double>();
					timeDim.value2obj.put("" + obj.timeClusterID, timeValue);
				}
				timeValue.put(obj.getDbId(), 1.0);
			}
			// event -----------
			for (String eventTag : obj.getEventTags().keySet()) {
				double prob = obj.getEventTags().get(eventTag);
				HashMap<Long, Double> eventValue = eventDim.value2obj
						.get(eventTag);
				if (eventValue == null) {
					eventValue = new HashMap<Long, Double>();
					eventDim.value2obj.put(eventTag, eventValue);
				}
				eventValue.put(obj.getDbId(), prob);
			}
			// userId -----------
			HashMap<Long, Double> idValue = idDim.value2obj.get(obj.userId);
			if (idValue == null) {
				idValue = new HashMap<Long, Double>();
				idDim.value2obj.put(obj.userId, idValue);
			}
			idValue.put(obj.getDbId(), 1.0);
			// visual concepts -----------
			for (String concept : obj.getConcepts().keySet()) {
				double prob = obj.getConcepts().get(concept);
				HashMap<Long, Double> visualValue = visualDim.value2obj
						.get(concept);
				if (visualValue == null) {
					visualValue = new HashMap<Long, Double>();
					visualDim.value2obj.put(concept, visualValue);
				}
				visualValue.put(obj.getDbId(), prob);
			}
			// people -----------
			for (String people : obj.getPeople().keySet()) {
				double prob = obj.getPeople().get(people);
				HashMap<Long, Double> peopleValue = peopleDim.value2obj
						.get(people);
				if (peopleValue == null) {
					peopleValue = new HashMap<Long, Double>();
					peopleDim.value2obj.put(people, peopleValue);
				}
				peopleValue.put(obj.getDbId(), prob);
			}
		}
		List<Dimension> dimensions = new ArrayList<Dimension>();
		dimensions.add(timeDim);
		dimensions.add(eventDim);
		//dimensions.add(idDim);
		visualDim.xor = false;
		dimensions.add(visualDim);
		peopleDim.xor = false;
		dimensions.add(peopleDim);
		return dimensions;
	}

	public static void writeImage(Summary summary, String dir) {
		String outputDir = root + "/outputs/" + dir;
		File file = new File(outputDir);
		if (file.exists()) {
			for (File f : file.listFiles()) {
				f.delete();
			}
			file.delete();
		}
		file.mkdir();
		try {
			BufferedWriter bw = new BufferedWriter(new FileWriter(outputDir
					+ "/dimension.txt"));
			int count = 0;
			for (DataObject obj : summary.getMemoryTweets()) {
				ImageObj img = (ImageObj) obj;
				BufferedImage image = null;
				File imgFile = new File(img.path);
				image = ImageIO.read(imgFile);
				ImageIO.write(image, "jpg", new File(outputDir + "/"
						+ (++count) + "_" + img.contentBasedName() + ".jpg"));
			}
			bw.flush();
			bw.close();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	public static void visualize(HashMap<Long, DataObject> objects,
			List<Dimension> dimensions, ArrayList<Double> weights,
			double alpha, double beta, double gamma) {
		ArrayList<InfoUnit> infoUnits = new ArrayList<InfoUnit>();
		double[][] probs = Preprocess.prepareForSummarization(objects,
				dimensions, weights, infoUnits);
		ArrayList<Summarizer> summarizers = new ArrayList<Summarizer>();
		summarizers.add(new GreedySummarizerItOptNewFilter(probs, infoUnits,
				alpha, beta, gamma));
		summarizers.add(new ClusterSummarizer());
		//summarizers.add(new PinakiSummarizer(probs, alpha, beta, gamma));
		summarizers.add(new RandomSummarizer());
		ArrayList<Summary> summaries = new ArrayList();
		for (int i = 0; i < summarizers.size(); i++) {
			Summary summary = summarizers.get(i).computeSummary(10, 1,
					(HashMap<Long, DataObject>) objects.clone(),
					dimensions.size());
			summaries.add(summary);
			writeImage(summary, summarizers.get(i).toString());
		}
		writeRandomInfo(objects, 20, summaries);
	}

	public static void writeRandomInfo(HashMap<Long, DataObject> objects,
			int k, ArrayList<Summary> summaries) {
		ArrayList<DataObject> objs = new ArrayList();
		for (DataObject obj : objects.values()) {
			objs.add(obj);
		}
		int times = 1000;
		double[] total = new double[summaries.size()];
		for (int i = 0; i < times; i++) {
			int count = 0;
			ArrayList<InfoUnit> result = new ArrayList();
			while (true) {
				int objId = new Random().nextInt(objs.size());
				ArrayList<Pair<Double, InfoUnit>> units = objs.get(objId)
						.getUnits();
				int unitId = new Random().nextInt(units.size());
				Pair<Double, InfoUnit> pair = units.get(unitId);
				if (pair.a() > new Random().nextDouble()) {
					count++;
					result.add(pair.b());
					if (count >= k) {
						break;
					}
				}
			}
			count = 0;
			for (InfoUnit unit : result) {
				for (int l = 0; l < summaries.size(); l++) {
					boolean hit = false;
					for (DataObject obj : summaries.get(l).getMemoryTweets()) {
						for (Pair<Double, InfoUnit> pair : obj.getUnits()) {
							if (pair.a() > new Random().nextDouble()
									&& pair.b().getInternId() == unit
											.getInternId()) {
								hit = true;
								break;
							}
						}
						if (hit) {
							break;
						}
					}
					if (hit) {
						total[l]++;
					}
				}
			}
		}
		for (int i = 0; i < total.length; i++) {
			System.out.println(total[i] / times / k);
		}
	}

	public static void main(String[] args) {
		ArrayList<ImageObj> imgs = readData(root + "/images");
		TimeClustering.cluster(imgs, 15,10);
		List<Dimension> dims = generateDim(imgs);
		HashMap<Long, DataObject> objects = new HashMap<Long, DataObject>();
		for (ImageObj img : imgs) {
			objects.put(img.getDbId(), img);
		}
		ArrayList<Double> weights = new ArrayList<Double>();
		for (int i = 0; i < dims.size(); i++) {
			weights.add(1.0);
		}
		 MainExp.runSummarizer(objects, dims, weights, 0.0, 0.0, 1);
		//visualize(objects, dims, weights, 0.0, 0.0, 1);
		// RobustExp.testRobust(objects, dims, weights, 0.3, 0.0, 1);
	}

}
